package com.mijie.homi.service.mood;

import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.mijie.homi.common.domain.mood.Mood;
import com.mijie.homi.common.domain.session.Session;
import com.mijie.homi.common.domain.user.Setting;
import com.mijie.homi.common.domain.user.User;
import com.mijie.homi.dao.mood.MoodPushQueueDao;
import com.mijie.homi.dao.mood.ReceiveNearbyMoodCounterDao;
import com.mijie.homi.domain.mood.MoodPushObject;
import com.mijie.homi.domain.mood.ReceiveNearbyMoodCounter;
import com.mijie.homi.service.notify.NotifyUserAgent;
import com.mijie.homi.service.session.SessionService;
import com.mijie.homi.service.user.SettingService;
import com.mijie.homi.service.user.UserService;
import com.mijie.util.DateUtil;
import com.mijie.util.Helper;

@Service
public class MoodBroadcastService {

	@Autowired
	private MoodPushQueueDao pushQueueDao;
	@Autowired
	private ReceiveNearbyMoodCounterDao receiveNearbyMoodCounterDao;
	@Autowired
	private SettingService settingService;
	@Autowired
	private UserService userService;
	@Autowired
	private NotifyUserAgent notifyUserAgent;
	@Autowired
	private SessionService sessionService;
	
	private Logger logger = Logger.getLogger(MoodBroadcastService.class);
	
	private AtomicBoolean broadcastWorkerIdle = new AtomicBoolean(true);
	
	public void addToMoodPushQueue(Mood mood){
		if(mood.getBroadcasted()==1 && mood.getContainsDisabledWord()==0 && Helper.wordCounter(mood.getContent(), true)>=5){
			MoodPushObject pushObject = new MoodPushObject();
			pushObject.setCreateAt(new Date());
			pushObject.setId(Helper.genUUID());
			pushObject.setMoodRecordId(mood.getId());
			pushObject.setAuthor(mood.getUserId());
			pushQueueDao.putToMoodPushQueue(pushObject);
			wakeupBroadcastWorker();
		}
	}
	
	private List<MoodPushObject>  moodPushQueue = null;
	public void wakeupBroadcastWorker(){
		if(broadcastWorkerIdle.get() && broadcastWorkerIdle.compareAndSet(true, false)){
			boolean continueBroadcast = false;
			MoodPushObject pushObject = null;
			if(moodPushQueue==null || moodPushQueue.isEmpty()){
				moodPushQueue = pushQueueDao.pullFromMoodPushQueue(10);
			}
			
			try{
				while(true){
					if(moodPushQueue==null || moodPushQueue.isEmpty()) {
						moodPushQueue = pushQueueDao.pullFromMoodPushQueue(10);
						if(moodPushQueue.isEmpty()){
							broadcastWorkerIdle.set(true);
//							logger.info("doMoodBroadcast,moodPushQueue isEmpty ,set broadcastWorkerIdle to true");
							break;
						}
					}
					
					logger.info("doMoodBroadcast,moodPushQueue size :"+moodPushQueue.size());
					Iterator<MoodPushObject> iter = moodPushQueue.iterator();
					while(iter.hasNext()){
						pushObject = iter.next();
						continueBroadcast = doMoodBroadcast(pushObject);
						
						if(continueBroadcast){
							logger.info("doMoodBroadcast,remove mood["+pushObject.getMoodRecordId()+"] from push queue.");
							pushQueueDao.removeFromMoodPushQueue(pushObject.getId());
							pushHistory.remove(pushObject.getId());
							iter.remove();
						}else{
							broadcastWorkerIdle.set(true);
							logger.info("doMoodBroadcast,nobody receive the mood broadcast,worker stop  working until someone login.set broadcastWorkerIdle to true");
							return;
						}
					}
				}
			}catch(Exception e){
				logger.error(e.getMessage(), e);
				broadcastWorkerIdle.set(true);
			}
		}else{
			logger.info("doMoodBroadcast,broadcastWorker is working.");
		}
	}
	
	private int moodPushReceiveIndex = 0;
	private Map<String,Set<Integer>> pushHistory = new HashMap<String,Set<Integer>>();
	private Set<Integer> receiverSet = null;
	private List<Setting> receiveNearbyMoodUserList = null;
	private static int MAX_BROADCAST_TIMES = 5;
	private static int MOOD_MAX_ALIVE = 60 * 6;
	private boolean doMoodBroadcast(MoodPushObject pushObject){
		Setting receiverSetting = null;
		String today = null;
		Setting setting = null;
		Session session = null;
		int reloadCounter = 0;
		while(true){
			if(pushObject.getBroadcastCounter()<MAX_BROADCAST_TIMES 
					&& DateUtil.getMinuteInterval(pushObject.getCreateAt(), new Date()) <= MOOD_MAX_ALIVE){
				if(receiveNearbyMoodUserList==null || receiveNearbyMoodUserList.size()<=moodPushReceiveIndex){
					if(reloadCounter>0) return false;
					receiveNearbyMoodUserList = settingService.listReceiveNearbyMoodUserId();
					moodPushReceiveIndex = 0;
					if(receiveNearbyMoodUserList==null){
//						logger.info("doMoodBroadcast cancel because receiver list is empty.");
						return false;
					}
					reloadCounter++;
//					logger.info("doMoodBroadcast moodPushReceiveIndex reset to zero.receiver list size:"+receiveNearbyMoodUserList.size());
				}
				
				receiverSetting = receiveNearbyMoodUserList.get(moodPushReceiveIndex++);
				if(receiverSetting==null){
					continue;
				}
				
				session = sessionService.getSessionByUserId(receiverSetting.getUserId());
				if(session==null || session.getAppVer().trim().isEmpty() || Helper.versionLessThan(session.getAppVer(), "1.0.6")){
//					logger.info("doMoodBroadcast skip because client version less than 1.0.6");
					continue;
				}
				
				if(!receiverSetting.getReceiverNearbyMoodFilter().equals(0)){
					//接收者设置了接收条件
					User author = userService.getUserById(pushObject.getAuthor());
					if(author!=null){
						if(!author.getGender().equals(receiverSetting.getReceiverNearbyMoodFilter())){
//							logger.info("doMoodBroadcast skip because receiver["+receiverSetting.getUserId()+"] filter is works!");
							continue;
						}
					}else{
						//心情作者不存在，作废该条心情广播
						pushObject.setBroadcastCounter(MAX_BROADCAST_TIMES);
						moodPushReceiveIndex--;
						logger.info("doMoodBroadcast skip because mood author not found.drop this moodpush.");
						continue;
					}
				}
				
				ReceiveNearbyMoodCounter counter = receiveNearbyMoodCounterDao.getReceiveNearbyMoodCounter(receiverSetting.getUserId());
				today = DateUtil.getTodayStr();
				if(counter==null){
					counter = new ReceiveNearbyMoodCounter(receiverSetting.getUserId(),1,today);
				}else{
					if(counter.getCountAtDate().equals(today)){
						if(counter.getCount()<=receiverSetting.getReceiveNearbyMoodLimit()-1){
							counter.setCount(counter.getCount()+1);
						}else{
//							logger.info("doMoodBroadcast skip because receiver["+receiverSetting.getUserId()+"] receive limit["+receiverSetting.getReceiveNearbyMoodLimit()+"] overhead.");
							continue;
						}
					}else{
						counter.setCount(1);
						counter.setCountAtDate(today);
					}
				}
				
				receiverSet = pushHistory.get(pushObject.getId());
				if(receiverSetting.getUserId() == pushObject.getAuthor() || receiverSet!=null && receiverSet.contains(receiverSetting.getUserId())){
//					logger.info("doMoodBroadcast skip because receiver is the author or already received.");
					continue;
				}
				
				logger.info("doMoodBroadcast:"+(moodPushReceiveIndex-1)+",user:"+receiverSetting.getUserId()+",mood["+pushObject.getMoodRecordId()+"] broadcast count:"+pushObject.getBroadcastCounter());
				
				pushObject.setBroadcastCounter(pushObject.getBroadcastCounter()+1);
				if(receiverSet==null)
					receiverSet = new HashSet<Integer>(5);
				receiverSet.add(receiverSetting.getUserId());
				pushHistory.put(pushObject.getId(), receiverSet);
				notifyUserAgent.moodBroadcastNotify(pushObject, receiverSetting.getUserId());
				receiveNearbyMoodCounterDao.setReceiveNearbyMoodCounter(counter);
				reloadCounter = 0;
			}else{
				logger.info("doMoodBroadcast move next.");
				return true;
			}
		}
	}
}
